package com.example.tutorialspringbootstatemachine.builder;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.statemachine.config.StateMachineBuilder;
import org.springframework.stereotype.Component;

import java.util.EnumSet;

/**
 * @Author: jie lu
 * @Data: 2021/10/19
 * @Version: 1.0
 * @Description:
 **/
@Component
public class UserStateMachineBuilder {
    public StateMachine<States, Events> buildStateMachine(BeanFactory beanFactory) throws Exception {
        StateMachineBuilder.Builder<States, Events> builder = StateMachineBuilder.builder();
        // 状态机基础配置
        builder.configureConfiguration().withConfiguration().autoStartup(true).beanFactory(beanFactory).listener(new UserStateMachineListener());
        // 状态机状态配置
        builder.configureStates().withStates().initial(States.init).choice(States.offline)
                .states(EnumSet.allOf(States.class));
        // 状态机事务配置
        builder.configureTransitions().withExternal().source(States.init).target(States.offline).event(Events.login)
                .and().withChoice().source(States.offline).first(States.online, new LoginInitGuard()).last(States.invisible) // 如果满足条件，为在线，否则为隐身
                .and().withExternal().source(States.online).target(States.invisible).event(Events.to_invisible) // 在线到隐身
                .and().withExternal().source(States.online).target(States.busy).event(Events.to_busy) // 在线到繁忙
                .and().withExternal().source(States.online).target(States.offline).event(Events.to_offline)// 在线到离线
                .and().withExternal().source(States.invisible).target(States.online).event(Events.to_online) // 隐身到在线
                .and().withExternal().source(States.invisible).target(States.busy).event(Events.to_busy) // 隐身到繁忙
                .and().withExternal().source(States.invisible).target(States.offline).event(Events.to_offline) // 隐身到离线
                .and().withExternal().source(States.busy).target(States.online).event(Events.to_online) // 繁忙到在线
                .and().withExternal().source(States.busy).target(States.invisible).event(Events.to_invisible) // 繁忙到隐身
                .and().withExternal().source(States.busy).target(States.offline).event(Events.to_offline); // 繁忙到离线
        return builder.build();

    }
}